package org.snia.server.dispatcher;

import java.util.Map;
import java.util.Properties;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.snia.cdmi.ErrorCodes;
import org.snia.cdmi.auth.Principal;
import org.snia.cdmi.exception.BadRequestException;
import org.snia.cdmi.exception.InternalException;
import org.snia.cdmi.locator.KetamaNodeLocator;
import org.snia.cdmi.locator.Node;
import org.snia.cdmi.model.AccessControlList;
import org.snia.cdmi.model.Container;
import org.snia.cdmi.model.ContainerProperties;
import org.snia.cdmi.model.DataObject;
import org.snia.cdmi.model.DataObjectProperties;
import org.snia.cdmi.model.InputDataObject;
import org.snia.cdmi.model.MetaDataObject;
import org.snia.exception.BusinessException;
import org.snia.server.ejb.container.ContainerOperation;

/**
 * 主要的服务均采用独立集群方式
 * @author Administrator
 *
 */
public class ServiceHashDispatcher implements Dispatcher {
	private static Log log = LogFactory.getLog(ServiceHashDispatcher.class);

	private Principal principal;
	
	private InitialContext ctx = null;
	private ContainerOperation remote = null;
	
	@Override
	public void createContainer(Container container) {
		// 检查参数
		if (container == null || container.getName() == null) {
			throw new BadRequestException(ErrorCodes.InvalidArgument);
		}
		Properties pros = new Properties();
		pros.setProperty("java.naming.factory.initial",
				"org.jnp.interfaces.NamingContextFactory");
		
		Node node = KetamaNodeLocator.getLocator().getPrimary(container.getName());
		pros.setProperty("java.naming.provider.url", node.getHost() + ":" + "1099");
		
		try {
			ctx = new InitialContext(pros);
			remote = (ContainerOperation)ctx.lookup("ContainerBean/remote");
			remote.createContainer(container, principal);
		} catch (NamingException e) {
			throw new InternalException(ErrorCodes.InternalError);
		}		
	}

	@Override
	public void deleteContainer(String name) {
		//检查参数
		if(StringUtils.isBlank(name)){
			throw new BadRequestException(ErrorCodes.InvalidArgument);
		}
		
		Properties pros = new Properties();
		pros.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
		
		Node node = KetamaNodeLocator.getLocator().getPrimary(name);
		pros.setProperty("java.naming.provider.url", node.getHost() + ":" + "1099");
		
		try {
			ctx = new InitialContext(pros);
			remote = (ContainerOperation)ctx.lookup("ContainerBean/remote");
			remote.deleteContainer(name, this.principal);
		} catch (NamingException e) {
			throw new InternalException(ErrorCodes.InternalError);
		}
	}

	@Override
	public void setAccessControlPolicy(String name, AccessControlList acl) {
		//检查参数
		if(StringUtils.isBlank(name)){
			throw new BadRequestException(ErrorCodes.InvalidArgument);
		}
		if(acl == null || acl.getGrants().isEmpty()){
			return;
		}
		Properties pros = new Properties();
		pros.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
		
		Node node = KetamaNodeLocator.getLocator().getPrimary(name);
		pros.setProperty("java.naming.provider.url", node.getHost() + ":" + "1099");
		
		try {
			ctx = new InitialContext(pros);
			remote = (ContainerOperation)ctx.lookup("ContainerBean/remote");
			remote.setAccessControlPolicy(name, acl, this.principal);
		} catch (NamingException e) {
			throw new InternalException(ErrorCodes.InternalError);
		}
	}

	@Override
	public Map<String, String> getAccessControlList(String name) {
		//检查参数
		if(StringUtils.isBlank(name)){
			throw new BusinessException(ErrorCodes.InvalidArgument);
		}
		Properties pros = new Properties();
		pros.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
		Node node = KetamaNodeLocator.getLocator().getPrimary(name);
		pros.setProperty("java.naming.provider.url", node.getHost() + ":" + "1099");
		
		try {
			ctx = new InitialContext(pros);
			remote = (ContainerOperation)ctx.lookup("ContainerBean/remote");
			return remote.getAccessControlList(name, this.principal);
		} catch (NamingException e) {
			throw new InternalException(ErrorCodes.InternalError);
		}	
	}

	@Override
	public ContainerProperties getProperties(String name, boolean withMetadata) {
		//检查参数
		if(StringUtils.isBlank(name)){
			throw new BusinessException(ErrorCodes.InvalidArgument);
		}
		Properties pros = new Properties();
		pros.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
		Node node = KetamaNodeLocator.getLocator().getPrimary(name);
		pros.setProperty("java.naming.provider.url", node.getHost() + ":" + "1099");
		
		try {
			ctx = new InitialContext(pros);
			remote = (ContainerOperation)ctx.lookup("ContainerBean/remote");
			return remote.getProperties(name, withMetadata, this.principal);
		} catch (NamingException e) {
			throw new InternalException(ErrorCodes.InternalError);
		}
	}

	@Override
	public void setUserMetadata(String name, Map<String, String> meta) {
		//检查参数
		if(StringUtils.isBlank(name)){
			throw new InternalException(ErrorCodes.InvalidArgument);
		}
		
		if(meta == null || meta.size() == 0){
			return;
		}
		Properties pros = new Properties();
		pros.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
		Node node = KetamaNodeLocator.getLocator().getPrimary(name);
		pros.setProperty("java.naming.provider.url", node.getHost() + ":" + "1099");
		
		try {
			ctx = new InitialContext(pros);
			remote = (ContainerOperation)ctx.lookup("ContainerBean/remote");
			remote.setUserMetadata(name, meta, this.principal);
		} catch (NamingException e) {
			throw new InternalException(ErrorCodes.InternalError);
		}
	}

	@Override
	public Map<String, String> getUserMetadata(String name) {
		//检查参数
		if(StringUtils.isBlank(name)){
			throw new BusinessException(ErrorCodes.InvalidArgument);
		}
		Properties pros = new Properties();
		pros.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
		Node node = KetamaNodeLocator.getLocator().getPrimary(name);
		pros.setProperty("java.naming.provider.url", node.getHost() + ":" + "1099");
		
		try {
			ctx = new InitialContext(pros);
			remote = (ContainerOperation)ctx.lookup("ContainerBean/remote");
			return remote.getUserMetadata(name, this.principal);
		} catch (NamingException e) {
			throw new InternalException(ErrorCodes.InternalError);
		}
	}

	@Override
	public void setAuthorization(Principal principal) {
		this.principal = principal;		
	}

	@Override
	public void createDataObject(InputDataObject object) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void deleteDataObject(String container, String objectUri) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public DataObject getDataObject(String container, String objectUri) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setAccessControlPolicy(String container, String objectUri,
			AccessControlList acl) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setUserMetadata(String container, String objectUri,
			Map<String, String> mapMeta) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Map<String, String> getUserMetadata(String container,
			String objectUri) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public DataObjectProperties getProperties(String container,
			String objectUri, boolean withMetadata) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Map<String, String> getAccessControlList(String container,
			String objectUri) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public MetaDataObject copyDataObject(String source, String container,
			String objectUri, boolean replaceFlag) {
				return null;
		// TODO Auto-generated method stub
	}

}
